/*
@author harley-dog

1.计算压力支撑位
2.计算布林轨
3.确定有效压力支撑位
    确定方法
    1.从昨日起往前循环找压力位，如果上一个压力位低于当前压力位，则停止查找，认为该压力位为有效压力位
    2.从昨日起往前循环找支撑位，如果上一个支撑位高于当前支撑位，则停止查找，认为该支撑位为有效支撑位
4.确定布林轨有效值
    1.布林轨最高值确定方法
    从有效压力位截止到昨天为止，找出这中间最高的一个布林轨中值，确定为布林轨最高值
    2.布林轨最低值确定方法
    从有效支撑位截止到昨天为止，找出这中间最低的一个布林轨中值，确定为布林轨最低值
5.判定趋势方法
    1.昨天无趋势的判定方法（首次判定）
        多头趋势：当天布林轨中值 高于 布林轨最高值 和 布林轨最低值
        空头趋势：当天布林轨中值 低于 布林轨最低值 和 布林轨最高值
        震荡趋势：以上两者都不满足，则为震荡趋势

    2.昨天有趋势的判定方法（趋势逆转）
        多头趋势 -> 震荡趋势 ：昨天为多头趋势，今天布林轨 低于 昨天的布林轨中值 ，则转为震荡趋势
        多头趋势 -> 空头趋势 ：昨天为多头趋势，今天布林轨 低于 布林轨最低值 ，且在有效支撑位到昨天之间，存在收盘价低于有效支撑位价格的一根阴柱

        空头趋势 -> 震荡趋势 ：昨天为空头趋势，今天布林轨 高于 昨天的布林轨中值 ，则转为震荡趋势
        空头趋势 -> 多头趋势 ：昨天为空头趋势，今天布林轨 高于 布林轨最低值 ，且在有效压力位到昨天之间，存在收盘价高于有效压力位价格的一根阳柱

        震荡趋势 -> 多头趋势 ：昨天为震荡趋势，今天布林轨 高于 布林轨最高值 ，且在有效压力位到昨天之间，存在收盘价高于有效压力位价格的一根阳柱
        震荡趋势 -> 空头趋势 ：昨天为震荡趋势，今天布林轨 低于 布林轨最低值 ，且在有效支撑位到昨天之间，存在收盘价低于有效支撑位价格的一根阴柱
*/
package cn.skyquant.quant4j.jforex.strategy.trend;

import cn.skyquant.quant4j.api.enums.Trend;
import cn.skyquant.quant4j.api.quant.TimeBar;
import cn.skyquant.quant4j.api.ylzc.YlzcDTO;
import cn.skyquant.quant4j.api.ylzc.ZigZag;
import cn.skyquant.quant4j.jforex.sdk.strategy.InstrumentEntity;
import cn.skyquant.quant4j.jforex.sdk.strategy.MA;
import cn.skyquant.quant4j.jforex.sdk.strategy.TimeBoll;
import cn.skyquant.quant4j.jforex.sdk.util.QuantUtil;
import cn.skyquant.quant4j.sdk.enums.YlzcType;
import cn.skyquant.quant4j.sdk.util.time.CalendarUtils;
import com.dukascopy.api.*;
import com.dukascopy.api.feed.IBarFeedListener;
import com.dukascopy.api.feed.IFeedDescriptor;

import java.util.*;

@Library("quant4j-api.jar;quant4j-sdk.jar;quant4j-jforex-sdk.jar;")
public class ZigZagTest implements IStrategy, IBarFeedListener {
    protected IEngine engine;
    protected IConsole console;
    protected IHistory history;
    protected IContext context;
    protected IIndicators indicators;
    protected IAccount account;

    @Configurable("上一次处于震荡期的时间")
    public Date lastTime;
    @Configurable("货币")
    public Instrument i1 = Instrument.EURUSD;
    @Configurable("大K线")
    public Period bigPeriod = Period.DAILY;
    @Configurable("压力支撑位:extDepth")
    public int zigzag_extDepth = 12;
    @Configurable("压力支撑位:ExtDeviation")
    public int zigzag_ExtDeviation = 6;
    @Configurable("压力支撑位:extDepth")
    public int zigzag_Backstep = 3;

    final Map<Instrument, InstrumentEntity> insMap = new HashMap<>();//交易品种实体
    final OfferSide offerSide = OfferSide.BID;

    @Override
    public void onStart(IContext context) throws JFException {
        this.engine = context.getEngine();
        this.console = context.getConsole();
        this.history = context.getHistory();
        this.context = context;
        this.indicators = context.getIndicators();
        this.account = context.getAccount();
        InstrumentEntity ie = new InstrumentEntity(i1);
        insMap.put(i1, ie);
        IChart chart = context.getChart(i1);
        if (lastTime == null) {
            console.getErr().println("start time can't be null");
            context.stop();
            return;
        }
        if (chart != null) {
            IFeedDescriptor feedDescriptor = chart.getFeedDescriptor();
            if (feedDescriptor != null) {
                feedDescriptor.setPeriod(bigPeriod);
                feedDescriptor.setOfferSide(offerSide);
                chart.setFeedDescriptor(feedDescriptor);
                chart.add(indicators.getIndicator("ZigZag"), new Object[]{zigzag_extDepth, zigzag_ExtDeviation, zigzag_Backstep});
                chart.repaint();
            }
        }
        context.subscribeToBarsFeed(i1, bigPeriod, offerSide, this);
        return;
    }


    @Override
    public void onBar(Instrument instrument, Period period, OfferSide offerSide, IBar bar) {
    }

    @Override
    public void onTick(Instrument instrument, ITick tick) throws JFException {
    }

    @Override
    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
    }

    @Override
    public void onMessage(IMessage message) throws JFException {
    }

    @Override
    public void onAccount(IAccount account) throws JFException {
    }

    @Override
    public void onStop() throws JFException {
    }

}
